home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1 / lisp / think-c / tc-receive.el < prev    next >
Encoding:
Text File  |  1994-03-23  |  26.8 KB  |  725 lines  |  [TEXT/EMAC]

  1. ;;;
  2. ;;; Implementation of the THINK Editor suite
  3. ;;;
  4. ;;; This file is part of the Macintosh port of GNU Emacs.
  5. ;;; Copyright (C) 1993 Marc Parmet.
  6. ;;;
  7.  
  8.  
  9. ; Events Sent From THINK To The Editor
  10. ; ====================================
  11. ; Open Document --- THINK sends this event when it wants the editor to open a text file.
  12. ; Event Class:    kCoreEventClass
  13. ; Event ID:        kAEOpenDocuments
  14. ; Parameters:    
  15. ;     
  16. ;     keyDirectObject (typeFSS, required)
  17. ;         The file to open.
  18. ;         
  19. ;     keyAEPosition (typeChar, optional)
  20. ;         A struct which may specify a selection range and/or accompanying error message.
  21. ;         The struct is defined as follows:
  22. ;                 
  23. ;         struct {                            
  24. ;             short showMsg;        //    if nonzero and line >= 0, display errmsg in an Alert.    
  25. ;             short line;            //    The line to be selected.
  26. ;             long start;            //    The start of the selection range (ignore if line>=0).
  27. ;             long end;            //    The end of the selection range (ignore if line>=0).
  28. ;             StringHandle errmsg;    //    The error message to display.
  29. ;             long    fileModDate;    //    The modification time of the disk file.
  30. ;         };
  31. ;         If line, start, and end are all negative, there is no selection range specified.
  32. ;         Otherwise, the selection range indicated by line or start/end should be selected
  33. ;         and the edit window should be scrolled to show this selection.
  34. ;         
  35. ;         If line>=0 and showMsg is nonzero, the error message at *errmsg should be 
  36. ;         displayed immediately after selecting and scrolling to the line.
  37.  
  38. (c:defstruct tc:struct-position ((short showMsg)
  39.                                  (short line)
  40.                                  (long start)
  41.                                  (long end)
  42.                                  (long errMsg)
  43.                                  (long fileModDate)))
  44.                                      
  45. ;;; This is called by the general OpenDocuments handler, which has special knowledge
  46. ;;; of this routine.
  47. (defun tc:parse-position-record (event)
  48.   (if tc:debug-trace (DebugStr "Emacs TPM code got ODOC event"))
  49.   (condition-case errmsg
  50.       (catch 'panic
  51.         (let* ((returnedType (make-string 4 0))
  52.                (data (make-string (c:sizeof 'tc:struct-position) 0))
  53.                (actualSize (make-string 4 0))
  54.                (junk (throw-err 
  55.                       (AEGetParamPtr event keyAEPosition typeChar returnedType
  56.                                      data (length data) actualSize)))
  57.                (showMsg (c:slotref 'tc:struct-position data 'showMsg))
  58.                (line (1+ (c:slotref 'tc:struct-position data 'line)))
  59.                (start (1+ (c:slotref 'tc:struct-position data 'start)))
  60.                (end (1+ (c:slotref 'tc:struct-position data 'end)))
  61.                (errMsg-handle (c:slotref 'tc:struct-position data 'errMsg)))
  62.           (setq tc:opened-from-TPM t)
  63.           (if (>= line 1)
  64.               (goto-line line)
  65.             (if (and (>= start 1) (>= end 1))
  66.                 (progn
  67.                   (goto-char start)
  68.                   (set-mark end)
  69.                   (if (not (input-pending-p))
  70.                       (progn
  71.                         (sit-for 1)
  72.                         (goto-char end)
  73.                         (if (not (input-pending-p))
  74.                             (sit-for 1))
  75.                         (goto-char start))))))
  76.           (if (and (not (zerop showMsg))
  77.                    (>= line 0))
  78.               (progn
  79.                 (HLock errMsg-handle)
  80.                 (let ((errMsg-ptr (deref errMsg-handle)))
  81.                   (message (concat "TPM message: "
  82.                                    (extract-internal errMsg-ptr 0 'pascal-string))))
  83.                 (HUnlock errMsg-handle)))
  84.           (bring-emacs-to-the-front)))
  85.     (error (if tc:debug-failures (DebugStr "Couldn't complete ODOC"))
  86.            errAEEventNotHandled)))
  87.  
  88. ; -----------------------------------------------------------------------
  89. ; -----------------------------------------------------------------------
  90. ;
  91. ; Modified --- THINK sends the Modified event when it needs to know which files have been 
  92. ;              modified and when they've been modified.  Send back a list of the following 
  93. ;              structs as the direct object of the reply event (one struct for each open 
  94. ;              file that has been modified).
  95. ;         
  96. ; Event Class:    'KAHL'
  97. ; Event ID:        'MOD '
  98. ; Parameters:        none
  99. ;     struct {
  100. ;         FSSpec     fss;    //    the file spec
  101. ;         long    when;    //    the time the file was last modified
  102. ;         short    saved;    //    ??? when replying to the Modified event, set 'saved' to zero
  103. ;     };
  104.  
  105. (AEInstallEventHandler "KAHL" "MOD " 'tc:do-modified-event 0 0)
  106.  
  107. (c:defstruct tc:struct-modified ((FSSpec fss)
  108.                                  (long when)
  109.                                  (short saved)))
  110.  
  111. (defun tc:do-modified-event (event reply refCon)
  112.   (if tc:debug-trace (DebugStr "Emacs TPM code got MOD event"))
  113.   (condition-case errmsg
  114.       (catch 'panic
  115.         (let* ((file-list (tc:relevant-buffers))
  116.                (ae-list (make-string sizeof-AEDescList 0))
  117.                now
  118.                spec
  119.                (modified-record (make-string (c:sizeof 'tc:struct-modified) 0)))
  120. ;(DebugStr "In do-mod, file-list is " file-list)
  121.           (throw-err (AECreateList 0 0 0 ae-list))
  122.           (GetDateTime now)
  123.           (while file-list
  124.             (if (and (nth 1 (car file-list))  ; File name associated with buffer
  125.                      (nth 2 (car file-list))) ; Buffer modified since last save
  126.                 (progn
  127. ;(DebugStr "Looking at " (nth 1 (car file-list)))
  128.                   (throw-err (unix-filename-to-FSSpec (nth 1 (car file-list)) spec))
  129.                   (c:slotset 'tc:struct-modified modified-record 'fss spec)
  130.                   (c:slotset 'tc:struct-modified modified-record 'when (- now 5))
  131.                   (c:slotset 'tc:struct-modified modified-record 'saved 0)
  132.                   (throw-err (AEPutPtr ae-list 0 typeChar modified-record
  133.                                        (length modified-record)))))
  134.             (setq file-list (cdr file-list)))
  135. ;(DebugStr "In do-mod, adding direct obj")
  136.           (throw-err (AEPutParamDesc reply keyDirectObject ae-list))
  137.           noErr))
  138.     (error (if tc:debug-failures (DebugStr "Couldn't complete MOD"))
  139.            errAEEventNotHandled)))
  140.  
  141. ; -----------------------------------------------------------------------
  142. ; -----------------------------------------------------------------------
  143. ;
  144. ; Get Text --- THINK sends this event when it needs to get a current copy of the file
  145. ;              (for compilation or debugging).
  146. ;         
  147. ; Event Class:    'KAHL'
  148. ; Event ID:        'GTTX'
  149. ; Parameters:
  150. ;     keyDirectObject (typeChar, required)
  151. ;         A struct which specifies the file THINK is looking for, and where the editor
  152. ;         should return the requested information.
  153. ;         
  154. ;         struct {
  155. ;             FSSpec fss;        //    the file THINK is looking for
  156. ;             Handle textH;    //    where to return the file's text
  157. ;             FTRec *ftp;        //    where to return the font/tabs info 
  158. ;                             //    (ftp == 0 if compiling).  This info is used to format
  159. ;                             //    the file's display in the Debugger's Source window.
  160. ;             long *modified;    //    where to return the time-modified of the file
  161. ;         };
  162.  
  163. (AEInstallEventHandler "KAHL" "GTTX" 'tc:do-gttx-event 0 0)
  164.  
  165. (c:defstruct tc:struct-gttx ((FSSpec fss)
  166.                              (long textH)
  167.                              (long ftp)
  168.                              (long modified)))
  169.  
  170. (c:defstruct tc:struct-FTRec ((short fontNum)
  171.                               (short fontSize)
  172.                               (short spaceWidth)
  173.                               (short tabStops)))
  174.  
  175. (defun tc:do-gttx-event (event reply refCon)
  176.   (if tc:debug-trace (DebugStr "Emacs TPM code got GTTX event"))
  177.   (condition-case errmsg
  178.       (catch 'panic
  179.         (let* ((returnedType (make-string 4 0))
  180.                (actualSize (make-string 4 0))
  181.                (gttx-msg (make-string (c:sizeof 'tc:struct-gttx) 0))
  182.                now
  183.                (junk1 (throw-err
  184.                       (AEGetParamPtr event keyDirectObject typeChar returnedType
  185.                                      gttx-msg (c:sizeof 'tc:struct-gttx) actualSize)))
  186.                (spec (c:slotref 'tc:struct-gttx gttx-msg 'fss))
  187.                (textH (c:slotref 'tc:struct-gttx gttx-msg 'textH))
  188.                (ftp (c:slotref 'tc:struct-gttx gttx-msg 'ftp))
  189.                (modified (c:slotref 'tc:struct-gttx gttx-msg 'modified))
  190.                (filename (FSSpec-to-unix-filename spec))
  191.                (junk2 (if (integerp filename) (throw 'panic filename)))
  192.                (old-buffer (current-buffer))
  193.                (buffer (get-file-buffer filename)))
  194.           (if (not buffer) (throw 'panic errAEEventNotHandled))
  195.           (set-buffer buffer)
  196.           (SetHandleSize textH (buffer-size))
  197.           (if (not (zerop (MemError))) (throw 'panic (MemError)))
  198.           (if tc:debug-trace (DebugStr "Moving " (buffer-size) " bytes to " textH))
  199.           (subst-char-in-region (point-min) (point-max) 10 13 t)
  200.           (HLock textH)
  201.           (BlockMove (buffer-string) (StripAddress (deref textH)) (buffer-size))
  202.           (HUnlock textH)
  203.           (subst-char-in-region (point-min) (point-max) 13 10 t)
  204.           
  205.           (if (not (zerop ftp))
  206.               (progn
  207.                 (if tc:debug-trace (DebugStr "Filling in ftp record"))
  208.                 (tc:send-mkup buffer)
  209.                 (if (not (zerop (tc:lineOffsets)))
  210.                     (progn (DisposHandle (tc:lineOffsets)) (setf-tc:lineOffsets 0)))
  211.                 (remake-lineOffsets)
  212.                 ;;; Need more accurate values here.
  213.                 (c:slotset 'tc:struct-FTRec ftp 'fontNum 4)
  214.                 (c:slotset 'tc:struct-FTRec ftp 'fontSize 9)
  215.                 (c:slotset 'tc:struct-FTRec ftp 'spaceWidth 6)
  216.                 (c:slotset 'tc:struct-FTRec ftp 'tabStops tab-width)))
  217.           
  218.           (GetDateTime now)
  219.           (encode-internal modified 0 'long (if (buffer-modified-p) (- now 5) 0))
  220.           (set-buffer old-buffer)
  221.           noErr))
  222.     (error (if tc:debug-failures (DebugStr "Couldn't complete GTTX"))
  223.            errAEEventNotHandled)))
  224.  
  225. ; -----------------------------------------------------------------------
  226. ; -----------------------------------------------------------------------
  227. ;
  228. ; Get Debugger State --- THINK sends this event when it needs to get the current Debugger 
  229. ;                        state information for the file (when debugging).  
  230. ; Event Class:    'KAHL'
  231. ; Event ID:        'GTDS'
  232. ; Parameters:
  233. ;     keyDirectObject (typeChar, required)
  234. ;         A struct which indicates the file THINK is looking for, the type of information
  235. ;         THINK wants, and where the editor should return the requested information.
  236. ;         Refer to the MiniEdit source code to see how to access and return the data.
  237. ;         typedef struct {
  238. ;             short             fileNum;        /*    for THINK's internal use    */
  239. ;             long            rsrcType;        /*    'BKPT' or 'DTVU'            */
  240. ;             short             rsrcID;            /*    ID of desired resource        */
  241. ;             void            *rsrcH;            /*    Handle to resource data        */
  242. ;         } getStateMsg;
  243. ;         struct {
  244. ;             FSSpec fss;            //    The file of interest
  245. ;             getStateMsg *msg;
  246. ;         };
  247.  
  248. (c:defstruct tc:struct-fssPlus ((FSSpec fss)
  249.                                 (long getStateMsg)))
  250.  
  251. (c:defstruct tc:struct-getStateMsg ((short fileNum)
  252.                                     ((array char 4) rsrcType)
  253.                                     (short rsrcID)
  254.                                     (long rsrcH)))
  255.  
  256. (AEInstallEventHandler "KAHL" "GTDS" 'tc:do-gtds-event 0 0)
  257.  
  258. (defun tc:do-gtds-event (event reply refCon)
  259.   (if tc:debug-trace (DebugStr "Emacs TPM code got GTDS event"))
  260.   (condition-case errmsg
  261.       (catch 'panic
  262.         (let* ((resultType (make-string 4 0))
  263.                (data (make-string (c:sizeof 'tc:struct-fssPlus) 0))
  264.                (actualSize (make-string 4 0))
  265.                (junk (throw-err (AEGetParamPtr event keyDirectObject typeChar resultType
  266.                                                data (length data) actualSize)))
  267.                (spec (c:slotref 'tc:struct-fssPlus data 'fss))
  268.                (msg (c:slotref 'tc:struct-fssPlus data 'getStateMsg))
  269.                (rsrcType (c:slotref 'tc:struct-getStateMsg msg 'rsrcType))
  270.                (rsrcID (c:slotref 'tc:struct-getStateMsg msg 'rsrcID))
  271.                (filename (FSSpec-to-unix-filename spec))
  272.                (old-buffer (current-buffer))
  273.                (buffer (get-file-buffer filename)))
  274.           (if (not buffer) (throw 'panic errAEEventNotHandled))
  275.           (if tc:debug-trace (DebugStr "Resource type is " rsrcType " " rsrcID))
  276.           (set-buffer buffer)
  277.           (if (not tc:have-TPM-data) (throw 'panic errAEEventNotHandled))
  278.           (let ((dataHandle
  279.                  (cond
  280.                   ((equal rsrcType "DTVU")
  281.                    (find-rsrc (tc:dataviews) (tc:dtvuIDs) (tc:dtvuSizes)))
  282.                   ((equal rsrcType "BKPT")
  283.                    (find-rsrc (tc:breakpoints) (tc:bkptIDs) (tc:bkptSizes)))
  284.                   (t
  285.                    (throw 'panic errAEEventNotHandled)))))
  286.             (set-buffer old-buffer)
  287.             (c:slotset 'tc:struct-getStateMsg msg 'rsrcH dataHandle)
  288.             noErr)))
  289.     (error (if tc:debug-failures (DebugStr "Couldn't complete GTDS"))
  290.            errAEEventNotHandled)))
  291.  
  292. (defun find-rsrc (data IDs sizes)
  293.   (if (or (zerop data) (zerop IDs) (zerop sizes))
  294.       (throw 'panic errAEEventNotHandled))
  295.   (let* ((numIDs (/ (GetHandleSize IDs) (c:sizeof 'long)))
  296.          (rsrcIndex (lookup-rsrc-id IDs numIDs rsrcID))
  297.          (junk (if (not rsrcIndex) (throw 'panic errAEEventNotHandled)))
  298.          (thisSize (extract-internal (deref sizes) (* (c:sizeof 'long) rsrcIndex) 'long))
  299.          (offset (sum-sizes sizes rsrcIndex))
  300.          (dataHandle (NewHandle thisSize))
  301.          (err (MemError)))
  302.     (if (not (zerop err)) (throw 'panic err))
  303.     (HLock dataHandle)
  304.     (BlockMove (+ (deref data) offset) (deref dataHandle) thisSize)
  305.     (HUnlock dataHandle)
  306.     dataHandle))
  307.  
  308. (defun sum-sizes (size-list target-index)
  309.   (let ((i 0)
  310.         (sum 0))
  311.     (while (< i target-index)
  312.       (setq sum (+ sum (extract-internal (deref size-list) (* (c:sizeof 'long) i) 'long)))
  313.       (setq i (1+ i)))
  314.     sum))
  315.  
  316. (defun lookup-rsrc-id (id-list numIDs targetID)
  317.   (let ((i 0)
  318.         (result nil))
  319.     (while (< i numIDs)
  320.       (let ((thisID (extract-internal (deref id-list) (* (c:sizeof 'long) i) 'long)))
  321.         (if tc:debug-trace (DebugStr "Comparing " thisID " and " targetID))
  322.         (if (= thisID targetID)
  323.             (progn
  324.               (setq result i)
  325.               (setq i numIDs))
  326.           (setq i (1+ i)))))
  327.     result))
  328.  
  329. ; -----------------------------------------------------------------------
  330. ; -----------------------------------------------------------------------
  331. ;
  332. ; Put Debugger State --- THINK sends this event when it needs to replace the Debugger state
  333. ;                        info for a file (when the THINK Debugger saves its current state).
  334. ;                        To respond to this event, the editor returns pointers to its 
  335. ;                        Debugger state info Handles (among other things) in the struct 
  336. ;                        type defined below.
  337. ; Event Class:    'KAHL'
  338. ; Event ID:        'PTDS'
  339. ; Parameters:
  340. ;     
  341. ;     keyDirectObject (typeChar, required)
  342. ;         A struct which indicates the file THINK is looking for, and where the editor
  343. ;         should return the requested information.  See the MiniEdit source code for more
  344. ;         details.
  345. ;     
  346. ;         struct {
  347. ;             FSSpec     fss;
  348. ;             long    ****pBkptIDs;
  349. ;             long    ****pDtvuIDs;
  350. ;             long    ****pBkptSizes;
  351. ;             long    ****pDtvuSizes;
  352. ;             Handle    **pMarkers;
  353. ;             Handle    **pBreakpoints;
  354. ;             Handle    **pDataviews;
  355. ;             short    ****pLineOffsets;
  356. ;             long     (**GetCharPos)(TEHandle, long);
  357. ;             short    (**GetLineNum)(TEHandle, long, long*);
  358. ;             long    *oldSelStart, *oldSelEnd, *oldTextLength, 
  359. ;                     *oldLineStart, *oldLineEnd, *oldNumLines,
  360. ;                     *newTextLength, *newNumLines, *newSelEnd,
  361. ;                     *refcon;
  362. ;         };
  363.  
  364. (c:defstruct tc:struct-ptds ((FSSpec fss)
  365.                              (long pBkptIDs)
  366.                              (long pDtvuIDs)
  367.                              (long pBkptSizes)
  368.                              (long pDtvuSizes)
  369.                              (long pMarkers)
  370.                              (long pBreakpoints)
  371.                              (long pDataviews)
  372.                              (long pLineOffsets)
  373.                              (long GetCharPos)
  374.                              (long GetLineNum)
  375.                              (long oldSelStart)
  376.                              (long oldSelEnd)
  377.                              (long oldTextLen)
  378.                              (long oldLineStart)
  379.                              (long oldLineEnd)
  380.                              (long oldNumLines)
  381.                              (long newTextLen)
  382.                              (long newNumLines)
  383.                              (long newSelEnd)
  384.                              (unsigned-long refCon)))
  385.  
  386. (AEInstallEventHandler "KAHL" "PTDS" 'tc:do-ptds-event 0 0)
  387.  
  388. (defun tc:do-ptds-event (event reply refCon)
  389.   (if tc:debug-trace (DebugStr "Emacs TPM code got PTDS event"))
  390.   (condition-case errmsg
  391.       (catch 'panic
  392.         (let* ((resultType (make-string 4 0))
  393.                (data (make-string (c:sizeof 'tc:struct-ptds) 0))
  394.                (actualSize (make-string 4 0))
  395.                (junk (throw-err (AEGetParamPtr event keyDirectObject typeChar resultType
  396.                                                data (length data) actualSize)))
  397.                (spec (c:slotref 'tc:struct-ptds data 'fss))
  398.                (filename (FSSpec-to-unix-filename spec))
  399.                (old-buffer (current-buffer))
  400.                (buffer (get-file-buffer filename)))
  401.           (if tc:debug-trace (DebugStr "ptds data is at " (string-data data)
  402.                                        ", buffer is " buffer))
  403.           (if (not buffer) (throw 'panic errAEEventNotHandled))
  404.           (set-buffer buffer)
  405.           (if (zerop tc:addressables) (throw 'panic errAEEventNotHandled))
  406.  
  407.           (mapcar (function (lambda (x)
  408.                               (encode-internal 
  409.                                (c:slotref 'tc:struct-ptds data (car x))
  410.                                0 'unsigned-long (cdr x))))
  411.                   (list
  412.                    (cons 'pBkptIDs (+ tc:addressables tc:bkptIDs-offset))
  413.                    (cons 'pDtvuIDs (+ tc:addressables tc:dtvuIDs-offset))
  414.                    (cons 'pBkptSizes (+ tc:addressables tc:bkptSizes-offset))
  415.                    (cons 'pDtvuSizes (+ tc:addressables tc:dtvuSizes-offset))
  416.                    (cons 'pMarkers (+ tc:addressables tc:markers-offset))
  417.                    (cons 'pBreakpoints (+ tc:addressables tc:breakpoints-offset))
  418.                    (cons 'pDataviews (+ tc:addressables tc:dataviews-offset))
  419.                    (cons 'pLineOffsets (+ tc:addressables tc:lineOffsets-offset))
  420.                    (cons 'GetCharPos tc:GetCharPos)
  421.                    (cons 'GetLineNum tc:GetLineNum)
  422.                    (cons 'oldSelStart tc:oldSelStart)
  423.                    (cons 'oldSelEnd tc:oldSelEnd)
  424.                    (cons 'oldTextLen tc:oldTextLen)
  425.                    (cons 'oldLineStart tc:oldLineStart)
  426.                    (cons 'oldLineEnd tc:oldLineEnd)
  427.                    (cons 'oldNumLines tc:oldNumLines)
  428.                    (cons 'newTextLen (tc:textLen))
  429.                    (cons 'newNumLines (tc:numLines))
  430.                    (cons 'newSelEnd (tc:selEnd))
  431.                    (cons 'refCon buffer)))
  432.           (set-buffer old-buffer)
  433.           noErr))
  434.     (error (if tc:debug-failures (DebugStr "Couldn't complete PTDS"))
  435.            errAEEventNotHandled)))
  436.  
  437. ; -----------------------------------------------------------------------
  438. ; -----------------------------------------------------------------------
  439. ;
  440. ; Window Search --- THINK sends this event whenever it needs to know whether the editor
  441. ;                   has a specific file open for editing.  If the file is open, send back 
  442. ;                   the file's modified time;  otherwise, return fnfErr (file not found).
  443. ; Event Class:    'KAHL'
  444. ; Event ID:        'SRCH'
  445. ; Parameters:
  446. ;     keyDirectObject (typeChar, required)
  447. ;         A struct which indicates the file THINK is looking for, and where the editor
  448. ;         should return the file's modified time.  See the MiniEdit source code for more
  449. ;         details.
  450. ;         struct {
  451. ;             FSSpec fss;            //    The file THINK is looking for.
  452. ;             long *modified;        //    Where to return the file's modified time.
  453. ;         };
  454.  
  455. (AEInstallEventHandler "KAHL" "SRCH" 'tc:do-srch-event 0 0)
  456.  
  457. (c:defstruct tc:struct-srch ((FSSpec fss)
  458.                              (long modified)))
  459.  
  460. (defun tc:do-srch-event (event reply refCon)
  461.   (if tc:debug-trace (DebugStr "Emacs TPM code got SRCH event"))
  462.   (condition-case errmsg
  463.       (catch 'panic
  464.         (let* ((returnedType (make-string 4 0))
  465.                (actualSize (make-string 4 0))
  466.                (srch-record (make-string (c:sizeof 'tc:struct-srch) 0))
  467.                now
  468.                (junk (throw-err
  469.                       (AEGetParamPtr event keyDirectObject typeChar returnedType
  470.                                      srch-record (c:sizeof 'tc:struct-srch) actualSize)))
  471.                (spec (c:slotref 'tc:struct-srch srch-record 'fss))
  472.                (modified (c:slotref 'tc:struct-srch srch-record 'modified))
  473.                (filename (FSSpec-to-unix-filename spec))
  474.                (buffer (get-file-buffer filename)))
  475.           (if (not buffer) (throw 'panic fnfErr))
  476.           (set-buffer buffer)
  477.           (GetDateTime now)
  478.           (encode-internal modified 0 'long (if (buffer-modified-p) (- now 5) 0))
  479.           noErr))
  480.     (error (if tc:debug-failures (DebugStr "Couldn't complete SRCH"))
  481.            errAEEventNotHandled)))
  482.  
  483. ; -----------------------------------------------------------------------
  484. ; -----------------------------------------------------------------------
  485. ;
  486. ; Marker Update --- THINK sends this event when it needs the editor to ensure that the 
  487. ;                   debugger state information is up-to-date.  Return the marker 
  488. ;                   information for EACH open file in an AEDescList composed of the 
  489. ;                   following structs.  See the MiniEdit code for details.
  490. ; Event Class:    'KAHL'
  491. ; Event ID:        'MKUP'
  492. ; Parameters:        none
  493. ;     struct {
  494. ;         Handle     markers, breakpoints, dataviews, lineOffsets, dtvuIDs;
  495. ;         long    oldSelStart, oldSelEnd, oldTextLength, 
  496. ;                 oldLineStart, oldLineEnd, oldNumLines,
  497. ;                 newTextLength, newNumLines, newSelEnd;
  498. ;         long     refcon;            
  499. ;     };
  500.  
  501. (c:defstruct tc:struct-mkup ((long markers)
  502.                              (long breakpoints)
  503.                              (long dataviews)
  504.                              (long lineOffsets)
  505.                              (long dtvuIDs)
  506.                              (long oldSelStart)
  507.                              (long oldSelEnd)
  508.                              (long oldTextLen)
  509.                              (long oldLineStart)
  510.                              (long oldLineEnd)
  511.                              (long oldNumLines)
  512.                              (long newTextLen)
  513.                              (long newNumLines)
  514.                              (long newSelEnd)
  515.                              (unsigned-long refCon)))
  516.  
  517. (defun make-mkup (buffer)
  518.   (let ((old-buffer (current-buffer))
  519.         (mkup (make-string (c:sizeof 'tc:struct-mkup) 0)))
  520.     (set-buffer buffer)
  521.     (if (not tc:have-TPM-data)
  522.         (progn
  523.           (set-buffer old-buffer)
  524.           nil)
  525.       (c:slotset 'tc:struct-mkup mkup 'markers (tc:markers))
  526.       (c:slotset 'tc:struct-mkup mkup 'breakpoints (tc:breakpoints))
  527.       (c:slotset 'tc:struct-mkup mkup 'dataviews (tc:dataviews))
  528.       (c:slotset 'tc:struct-mkup mkup 'lineOffsets (tc:lineOffsets))
  529.       (c:slotset 'tc:struct-mkup mkup 'dtvuIDs (tc:dtvuIDs))
  530.       (c:slotset 'tc:struct-mkup mkup 'oldSelStart tc:oldSelStart)
  531.       (c:slotset 'tc:struct-mkup mkup 'oldSelEnd tc:oldSelEnd)
  532.       (c:slotset 'tc:struct-mkup mkup 'oldTextLen tc:oldTextLen)
  533.       (c:slotset 'tc:struct-mkup mkup 'oldLineStart tc:oldLineStart)
  534.       (c:slotset 'tc:struct-mkup mkup 'oldLineEnd tc:oldLineEnd)
  535.       (c:slotset 'tc:struct-mkup mkup 'oldNumLines tc:oldNumLines)
  536.       (c:slotset 'tc:struct-mkup mkup 'newTextLen (tc:textLen))
  537.       (c:slotset 'tc:struct-mkup mkup 'newNumLines (tc:numLines))
  538.       (c:slotset 'tc:struct-mkup mkup 'newSelEnd (tc:selEnd))
  539.       (c:slotset 'tc:struct-mkup mkup 'refCon buffer)
  540.       (set-buffer old-buffer)
  541.       mkup)))
  542.  
  543. (AEInstallEventHandler "KAHL" "MKUP" 'tc:do-mkup-event 0 0)
  544.  
  545. (defun tc:do-mkup-event (event reply refCon)
  546.   (if tc:debug-trace (DebugStr "Emacs TPM code got MKUP event"))
  547.   (condition-case errmsg
  548.       (catch 'panic
  549.         (let* ((old-buffer (current-buffer))
  550.                (mkup-list (make-string sizeof-AEDescList 0))
  551.                (callback-data (encode-long-integer tc:GetLineNum)))
  552.           (throw-err (AEPutParamPtr reply "CLBK" typeChar callback-data (c:sizeof 'long)))
  553.           (throw-err (AECreateList 0 0 0 mkup-list))
  554.           (mapcar (function
  555.                    (lambda (x)
  556.                      (set-buffer (car x))
  557.                      (let ((mkup (make-mkup (car x))))
  558.                        (if mkup
  559.                            (throw-err
  560.                             (AEPutPtr mkup-list 0 typeChar mkup (length mkup)))))))
  561.                   (tc:relevant-buffers))
  562.           (throw-err (AEPutParamDesc reply keyDirectObject mkup-list))
  563.           (AEDisposeDesc mkup-list)
  564.           (set-buffer old-buffer)
  565.           noErr))
  566.     (error (DebugStr "Couldn't complete MKUP")
  567.            errAEEventNotHandled)))
  568.  
  569. ; -----------------------------------------------------------------------
  570. ; -----------------------------------------------------------------------
  571. ;
  572. ; Make LineOffsets --- THINK sends this event when it needs the editor to create a new
  573. ;                      lineOffsets array for EACH open file.
  574. ; Event Class:    'KAHL'
  575. ; Event ID:        'OFST'
  576. ; Parameters:        none
  577.  
  578. ;;    long nLines = GetNumLines(TEH);    //    Create a new lineOffsets array for THINK
  579. ;;    lineOffsets = (short**) NewHandleClear(sizeof(short) * (nLines+1));
  580. ;;    (*lineOffsets)[nLines] = 0x7FFF - nLines;
  581. ;;    return(noErr);
  582.  
  583. (AEInstallEventHandler "KAHL" "OFST" 'tc:do-ofst-event 0 0)
  584.  
  585. (defun tc:do-ofst-event (event reply refCon)
  586.   (if tc:debug-trace (DebugStr "Emacs TPM code got OFST event"))
  587.   (condition-case errmsg
  588.       (let* ((old-buffer (current-buffer)))
  589.         (mapcar (function (lambda (x) (set-buffer (car x)) (remake-lineOffsets)))
  590.                 (tc:relevant-buffers))
  591.         (set-buffer old-buffer)
  592.         noErr)
  593.     (error (if tc:debug-failures (DebugStr "Couldn't complete OFST"))
  594.            errAEEventNotHandled)))
  595.  
  596. (defun remake-lineOffsets ()
  597.   (let* ((nLines (tc:numLines))
  598.          (lineOffsets (NewHandleClear (* (c:sizeof 'short) (1+ nLines)))))
  599.     (if (not (zerop (MemError)))
  600.         (MemError)
  601.       (HLock lineOffsets)
  602.       (encode-internal (deref lineOffsets) (* nLines (c:sizeof 'short))
  603.                        'short (- (hex-string-to-int "7fff") nLines))
  604.       (HUnlock lineOffsets)
  605.       ;;; When do we know to dispose of the old lineOffsets?
  606.       (setf-tc:lineOffsets lineOffsets)
  607.       noErr)))
  608.         
  609. ; -----------------------------------------------------------------------
  610. ; -----------------------------------------------------------------------
  611. ;
  612. ; Failed Find In Next File --- THINK sends the Failed Find In Next File event to tell the 
  613. ;                              editor that its last FINF request has failed.
  614. ; Event Class:    'KAHL'
  615. ; Event ID:        'NONF'
  616. ; Parameters:        none
  617.  
  618. (AEInstallEventHandler "KAHL" "NONF" 'tc:do-nonf-event 0 0)
  619.  
  620. (defun tc:do-nonf-event (event reply refCon)
  621.   (if tc:debug-trace (DebugStr "Emacs TPM code got NONF event"))
  622.   (condition-case errmsg
  623.       (progn
  624.         (beep)
  625.         (message "No more instances found")
  626.         noErr)
  627.     (error (if tc:debug-failures (DebugStr "Couldn't complete NONF"))
  628.            errAEEventNotHandled)))
  629.  
  630. ; -----------------------------------------------------------------------
  631. ; -----------------------------------------------------------------------
  632. ;
  633. ; OpenProject
  634. ;     
  635. ;     THINK sends the OpenProject event to notify the editor that a project has just been
  636. ;     opened and/or closed.  (The direct parameter gives the details.)  
  637. ;     
  638. ;     If a project was closed, the user should be asked what to do with any open
  639. ;     sourcefiles that are related to the project:  save and close, discard changes and
  640. ;     close, or leave them open.  If some of the project's sourcefiles were indeed open,
  641. ;     the user should also be advised to perform a Use Disk the next time he opens the 
  642. ;     project.
  643. ;     
  644. ;     If a project was opened, and the editor already has one of the project's sourcefiles 
  645. ;     open, it may need to read in the file's marker data now.  If so, and the file has 
  646. ;     already been modified, the marker data will be out of sync;  the best we can do is 
  647. ;     revert to the previous saved version.
  648. ;     
  649. ;     See the MiniEdit code for an example of how to handle this event.
  650. ; Event Class:    'KAHL'
  651. ; Event ID:        'OPRJ'
  652. ; Parameters:
  653. ;     keyDirectObject (typeShortInteger, required)
  654. ;         0 == no change (you should never get this)
  655. ;         1 == a project was opened
  656. ;         2 == a project was closed
  657. ;         3 == a project was closed, then a project was opened
  658.  
  659. (AEInstallEventHandler "KAHL" "OPRJ" 'tc:do-oprj-event 0 0)
  660.  
  661. (defun tc:do-oprj-event (event reply refCon)
  662.   (if tc:debug-trace (DebugStr "Emacs TPM code got OPRJ event"))
  663.   errAEEventNotHandled)
  664.     
  665. ; -----------------------------------------------------------------------
  666. ; -----------------------------------------------------------------------
  667. ;
  668. ; CloseProject
  669. ;     
  670. ;     THINK sends the CloseProject event to notify the editor that the current project is
  671. ;     being closed.  The keyDirectObject parameter indicates whether the related sourcefiles
  672. ;     should be saved and closed (kAEYes) or closed but not saved (kAENo).  If the direct
  673. ;     object is kAEAsk, the user should be asked what to do with any open sourcefiles (an
  674. ;     option should be provided to cancel the project close, also.)
  675. ;     The editor can decide whether to complete or abort THINK's 
  676. ;     Close Project command by sending (or failing to send) THINK a CloseProject event in
  677. ;     reply.  See the MiniEdit code for an example of how to handle this event.
  678. ; Event Class:    'KAHL'
  679. ; Event ID:        'CPRJ'
  680. ; Parameters:
  681. ;     keyDirectObject (typeEnumerated, required)
  682. ;         kAEYes == save and close related sourcefiles;
  683. ;         kAENo  == close related sourcefiles, discarding changes;
  684. ;         kAEAsk == ask user what to do with related sourcefiles.
  685.  
  686. (AEInstallEventHandler "KAHL" "CPRJ" 'tc:do-cprj-event 0 0)
  687.  
  688. (defun tc:do-cprj-event (event reply refCon)
  689.   (if tc:debug-trace (DebugStr "Emacs TPM code got CPRJ event"))
  690.   (condition-case errmsg
  691.       (catch 'panic
  692.         (let* ((returnedType (make-string 4 0))
  693.                (actualSize (make-string 4 0))
  694.                (yes-no-ask (make-string 4 0)))
  695.           (throw-err (AEGetParamPtr event keyDirectObject typeLongInteger returnedType
  696.                                     yes-no-ask (c:sizeof 'long) actualSize))
  697.           
  698.             ;;; For now, we simply return noErr, which allows Think to close the
  699.             ;;; project without waiting for a CPRJ event from Emacs.
  700.           
  701.           noErr))
  702.     (error (if tc:debug-failures (DebugStr "Couldn't complete CPRJ"))
  703.            errAEEventNotHandled)))
  704.